home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SPACE 1
/
SPACE - Library 1 - Volume 1.iso
/
program
/
441
/
dlibs12
/
exec.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-23
|
5KB
|
237 lines
#include <stdio.h>
#include <osbind.h>
#include <string.h>
#include <basepage.h>
#include <malloc.h>
#include <errno.h>
typedef struct
{
char xarg_magic[4]; /* verification value "xArg" */
int xargc; /* argc */
char **xargv; /* argv */
char *xiovector; /* i/o handle status */
BASEPAGE *xparent; /* pointer to parent's basepage */
}
XARG;
static char xmagic[] = "xArg";
static char hex[] = "0123456789ABCDEF";
#define MAXFORK 8 /* maximum number of concurrent fork's */
typedef struct
{
int fk_pid;
char fk_rv;
char fk_xstatus;
}
FORK;
static FORK forktbl[MAXFORK];
#define XS_NORMAL 0x00 /* process terminated normally */
#define XS_RUNNING 0x7F /* process still running */
static FORK *forkp = forktbl; /* fork() context pointer */
static int forkcnt = 0; /* # of fork's currently active */
static char fork_ext[] = ".ttp\0.tos\0.prg\0.app\0";
/*
* Build TOS-style command line image from argv[] list.
*/
int makcmdln(cmdln, argv)
char *cmdln;
char **argv;
{
register char *p, *q, *e;
register int argc = 1;
p = cmdln + 1;
e = cmdln + 127;
while(q = *++argv) /* start at argv[1] */
{
++argc;
while(*q && p < e)
*p++ = *q++;
if (p < e)
*p++ = ' ';
}
*p = '\0';
cmdln[0] = p - (cmdln + 1); /* store the string length */
return(argc); /* return number of arguments */
}
forkl(pathname, arg0)
char *pathname, *arg0;
{
forkve(pathname, &arg0, NULL);
}
forkle(pathname, arg0)
char *pathname, *arg0;
{
register char **argv = &arg0, *envp;
register int argc;
char cmdln[130];
argc = makcmdln(cmdln, argv);
envp = argv[argc+1];
return(_exec(pathname, cmdln, argc, argv, envp));
}
int forklp(pathname, arg0)
char *pathname, *arg0;
{
char *pfindfile();
if(pathname = pfindfile(NULL, pathname, fork_ext))
return(forkve(pathname, &arg0, NULL));
return(errno = EFILNF);
}
int forklpe(pathname, arg0)
char *pathname, *arg0;
{
register char **argv = &arg0, *envp;
register int argc;
char cmdln[130];
char *pfindfile();
if(pathname = pfindfile(NULL, pathname, fork_ext))
{
argc = makcmdln(cmdln, argv);
envp = argv[argc+1];
return(_exec(pathname, cmdln, argc, argv, envp));
}
return(errno = EFILNF);
}
forkve(pathname, argv, envp)
char *pathname, **argv, *envp;
{
register int argc;
char cmdln[130];
argc = makcmdln(cmdln, argv);
return(_exec(pathname, cmdln, argc, argv, envp));
}
forkvpe(pathname, argv, envp)
char *pathname, **argv, *envp;
{
char *pfindfile();
if(pathname = pfindfile(NULL, pathname, fork_ext))
return(forkve(pathname, argv, envp));
return(errno = EFILNF);
}
FORK *_fork()
/*
* create FORK struct for new process and return calculated pid
*/
{
register long n;
register int pid;
register FORK *fp;
if((forkcnt >= MAXFORK) /* too many forks already active? */
|| ((n = Malloc(-1L)) <= 0)) /* malloc error? */
return(NULL);
n = Malloc(n); /* get address of next free block */
Mfree(n);
fp = forkp++;
++forkcnt;
n += 0x3EL; /* adjust it */
pid = (0x7FFF & (n>>8)); /* calculate pid from it */
fp->fk_pid = pid; /* initialize process entry */
fp->fk_xstatus = XS_RUNNING;
fp->fk_rv = 0;
return(fp);
}
int _exec(pathname, cmdln, argc, argv, envp)
char *pathname, *cmdln;
int argc;
char **argv, *envp;
{
register FORK *fp;
XARG xarg;
register XARG *xp = &xarg;
register char *p;
register int n;
register long rv;
char xenv[16];
if((fp = _fork()) == NULL)
return(ERROR);
/*
* initialize XARG struct
*/
strncpy(xp->xarg_magic, xmagic, 4);
xp->xargc = argc;
xp->xargv = argv;
xp->xiovector = NULL;
xp->xparent = _base;
/*
* create environment variable "xArg=XXXXXXXX"
*/
strcpy(xenv, xmagic);
p = strrchr(xenv, '\0'); /* move to terminating '\0' */
*p++ = '=';
rv = ((long) xp);
for(n=8; n--; rv >>= 4) /* convert long to ascii-hex */
p[n] = hex[rv & 0xF];
p[8] = '\0';
/*
* install environment variable and execute program
*/
putenv(xenv);
rv = Pexec(0, pathname, cmdln, envp);
putenv(xmagic); /* remove "xArg" from environment */
if(rv < 0L) /* GEMDOS error */
{
errno = ((int) rv);
fp->fk_rv = fp->fk_xstatus = ((char) rv);
}
else /* normal exit */
{
fp->fk_xstatus = XS_NORMAL;
fp->fk_rv = ((char) rv);
}
return(fp->fk_pid);
}
int wait(rvp)
char *rvp;
{
register FORK *fp;
register int pid;
fp = forktbl;
if(fp == forkp) /* no child processes */
return(errno = ERROR);
for(;;)
{
for(fp = forktbl; fp < forkp; ++fp)
{
if(fp->fk_xstatus != XS_RUNNING)
{
pid = fp->fk_pid;
if(rvp)
{
rvp[0] = fp->fk_rv;
rvp[1] = fp->fk_xstatus;
}
--forkp;
--forkcnt;
while(fp++ < forkp)
fp[-1] = fp[0];
return(pid);
}
}
sleep(1);
}
}